package com.louis.i18n;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.support.AbstractMessageSource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.stereotype.Component;

import com.louis.dao.GeneralDao;
import com.louis.domain.i18n.Message;
import com.louis.domain.i18n.Translation;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.*;

/**
 * @author Lijun jiang
 * @Date: May 13, 2011
 * @Time: 10:47:08 AM
 */
@Component("databaseMessageSource")
public class DatabaseMessageSource extends AbstractMessageSource implements InitializingBean, MessageSourceHandler {

	// the cache for message,all database message load to it
	private Map<String, Map<Locale, MessageFormat>>	cacheMessageFormatMap	= new HashMap<String, Map<Locale, MessageFormat>>();

	@Resource(name = "generalDao")
	private GeneralDao								generalDao;

	private String[]								propertiesNames			= new String[] { "content_en.properties", "content_zh_CN.properties" };

	private String[]								languages				= new String[] { "en", "zh_CN" };

	private List<Message>							cacheMessages			= new ArrayList<Message>();

	private List<Message>							needUpdateMessages;

	protected MessageFormat resolveCode(String code, Locale locale) {
		MessageFormat messageFormat = resolveMessageFormat(code, locale);
		if (messageFormat != null) {
			return messageFormat;
		}
		return new MessageFormat("The code of the message is not", Locale.ENGLISH);
	}

	private MessageFormat resolveMessageFormat(String code, Locale locale) {
		Map<Locale, MessageFormat> localeMessageFormatMap = cacheMessageFormatMap.get(code);
		if (localeMessageFormatMap != null) {
			MessageFormat messageFormat = localeMessageFormatMap.get(locale);
			if (messageFormat != null) {
				return messageFormat;
			}
		}
		return null;
	}

	public void afterPropertiesSet() throws Exception {
		loadMessage();
		loadProperties();
	}

	private void loadProperties() {
		needUpdateMessages = new ArrayList<Message>();
		if (propertiesNames.length == languages.length) {
			for (int i = 0; i < propertiesNames.length; i++) {
				loadProperties(propertiesNames[i], languages[i]);
			}
		}
		generalDao.saveOrUpdate(needUpdateMessages);
	}

	private void loadProperties(String propertiesName, String language) {
		try {
			Properties properties = PropertiesLoaderUtils.loadAllProperties(propertiesName);
			validatorMessage(properties, language);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void validatorMessage(Properties properties, String language) {
		Enumeration<Object> codes = properties.keys();
		while (codes.hasMoreElements()) {
			String code = codes.nextElement().toString();
			boolean hasCode = false;
			for (String cacheCode: cacheMessageFormatMap.keySet()) {
				if (code.equals(cacheCode)) {
					hasCode = true;
					break;
				}
			}
			String text = properties.get(code).toString();
			if (hasCode) {
				Message message = getMessage(code);
				List<Translation> translations = message.getTranslations();
				boolean hasTranslation = false;
				for (Translation translation: translations) {
					if (translation.getLanguage().equalsIgnoreCase(language)) {
						hasTranslation = true;
						break;
					}
				}
				if (!hasTranslation) {
					translations.add(new Translation(language, text, message));
					needUpdateMessages.add(message);
					cacheMessageFormatMap.put(message.getCode(), message.getMessageFormats());
				}
			} else {
				Message message = new Message();
				List<Translation> translations = new ArrayList<Translation>();
				translations.add(new Translation(language, text, message));
				message.setCode(code);
				message.setTranslations(translations);
				cacheMessages.add(message);
				needUpdateMessages.add(message);
				cacheMessageFormatMap.put(message.getCode(), message.getMessageFormats());
			}
		}
	}

	private Message getMessage(String code) {
		for (Message message: cacheMessages) {
			if (message.getCode().equalsIgnoreCase(code)) {
				return message;
			}
		}
		return null;
	}

	private void loadMessage() {
		cacheMessages = generalDao.query(Message.class, false);
		for (Message message: cacheMessages) {
			cacheMessageFormatMap.put(message.getCode(), message.getMessageFormats());
		}
	}

	public void synchronizationMessageSource(String code, List<MessageFormat> messageFormats) {

	}
}